/**
 * 组件的渲染：
 *    默认组件会渲染一次，然后当组件的 state 或 props 有变更时，会再次触发组件 render
 *
 * 一般来说当父组件Render，子组件一定会跟着Render。原因是子组件接受到的 Props 数据更新了。
 * 子组件继承的是 React.Component 内部会对 Props 数据做一个全等的比较
 *
 * 有时我们期望组件能够减少无用的Render.提供组件性能。这时可以让组件继承 React.PureComponent
 *    这时组件内接受到新的Props数据时，会与旧的Props做比较，比较的方式不再是全等比较，而是使用各种的属性来比较，当有不同的时候，组件就会Render。否则组件会阻止Render.
 *
 * 为什么解决this指向问题的四种方案中推荐使用其中两种：
 *    1. 如果是把函数传递给子组件去使用，且子组件实现了 PureComponent 为了减少 Render ，做性能优化。
 *    2. 这时使用 onClick={this.fn1.bind(this)} 与 onClick={() => {this.fn1()}} 都会在父组件Render的时候，生成一份新的函数给到子组件，子组件内比较新旧Props是就认为数据有变动从而没有阻止Render导致我们性能优化没有做到位。
 */

import React from "react";
import Hello from "./components/Hello";

class App extends React.Component {
  constructor(props: any) {
    super(props);

    this.fn2 = this.fn2.bind(this);
    // this.handleChange = this.handleChange.bind(this);
  }

  state: Readonly<{ count: number; name: string }> = {
    count: 10,
    name: "张三",
  };

  fn1() {
    this.setState({
      count: 100,
    });

    console.log("fn1", this);
  }

  fn2() {
    this.setState({
      count: 200,
    });
    console.log("fn2", this);
  }

  fn3() {
    this.setState({
      count: 300,
    });
    console.log("fn3", this);
  }

  // public class fields 语法 + 箭头函数
  fn4 = () => {
    this.setState({
      count: 400,
    });
    console.log("fn4", this);
  };

  handleChange = () => {
    console.log("handleChange");
    this.setState({
      name: "王五",
    });
  };

  render() {
    console.log("App render", this);

    return (
      <div>
        <h1>事件处理</h1>
        <p>Count: {this.state.count}</p>

        <Hello name={this.state.name} change={this.handleChange} />

        <hr />
        <button onClick={this.fn1.bind(this)}>按钮1</button>
        <button onClick={this.fn2}>按钮2</button>
        <button onClick={() => this.fn3()}>按钮3</button>
        <button onClick={this.fn4}>按钮4</button>
      </div>
    );
  }
}

export default App;

// const obj = {
//   name: "张三",

//   fn1() {
//     "use strict";
//     console.log(this);
//   },
// };

// obj.fn1(); // obj 这个对象

// const onClick = obj.fn1;

// onClick(); // window
